#ifndef __UDSF_APP_CFG_C__
#define __UDSF_APP_CFG_C__

#include "app.h"


/*
*   notice:
*   UDSF 同UDF编程：不可调用cstd-lib,只可调用"sdk_ifs_udk_cfg.h"、"sys_api.h"中列出的API函数。
*   UDSF文件内函数均需使用static修饰符，且UDF中以#include "udsf_xxx.c"形式引用
*/

#include "udsf_spiflash.c"
#include "udsf_crc.c"

#include "udsf_uart.c"
#include "udsf_memory_access.c"

// 读取自A/B区
static int udsf_cfg_load(uint8_t is_xip,uint8_t id,uint8_t *dst,uint16_t len){
	
	PARAM_CFG xxx;
	uint8_t* dst_tmp = (uint8_t*)&xxx;
	
	uint8_t cfg_location = APP_LOCATION_OUTER;
	
	udsf_memory_load2sram( SYSBOOT_AB_CFG_OUTER+id*SYSBOOT_AB_CFG_PER_SIZE+sizeof(sys_cfg_t),is_xip,cfg_location,dst_tmp,len,eQSPI_FLASH_STD);
	
	uint16_t crc = udsf_get_crc(dst_tmp,len-2);
	
	if( crc == *(uint16_t*)(&dst_tmp[len-2]) ){
		
		CSTD_MEMCPY((uint8_t*)dst,dst_tmp,len);
		return 0;
	}
	return -1;
}

static int udsf_udc_syscfg_load(uint8_t is_xip,uint8_t id,uint8_t *dst,uint16_t len){
	
	PARAM_CFG xxx;
	uint8_t* dst_tmp = (uint8_t*)&xxx;
	
	uint8_t cfg_location = APP_LOCATION_OUTER;
	
	udsf_memory_load2sram( SYSBOOT_AB_CFG_OUTER+id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,dst_tmp,len,eQSPI_FLASH_STD);
	
	uint16_t crc = udsf_get_crc(dst_tmp,len-2);
	
	if( crc == *(uint16_t*)(&dst_tmp[len-2]) ){
		CSTD_MEMCPY((uint8_t*)dst,dst_tmp,len);
		return 0;
	}
	return -1;
}

// 从UDP中恢复默认参数
static int udsf_cfg_default(uint8_t is_xip,uint8_t cfg_location,uint32_t offset,uint8_t *dst,uint16_t len){
	uint32_t udp_addr;

	if( cfg_location == APP_LOCATION_OUTER ){
		udp_addr = UDK_LITE_UDP_START_ADDR;
	}else{
		udp_addr = UDK_SE_UDP_START_ADDR;
	}

	udsf_memory_load2sram(udp_addr+offset+UDP_SIZE-len,is_xip,cfg_location,dst,len,eQSPI_FLASH_STD);
	return 0;
}

// 更新crc
static void udsf_cfg_update_crc(uint8_t *dst,uint16_t len){
	uint16_t crc = udsf_get_crc(dst,len-2);
	*(uint16_t*)(&dst[len-2]) = crc;
}

// 存储到A/B区
static int udsf_cfg_save(uint8_t is_xip,uint8_t curr_id,uint8_t *src,uint16_t len,uint8_t force){

	uint8_t new_id = (curr_id+1)%2;
	uint8_t cfg_location = APP_LOCATION_OUTER;
	
	udc_def_t xx;
	uint32_t new_sn;
	
	CSTD_MEMSET(&xx,0,sizeof(udc_def_t));

	if( force ){
		
		xx.sys_cfg.app_select_cfg.app_select = UDC_CFG_APP_SELECT;
		xx.sys_cfg.app_select_cfg.app_io[0] = UDC_CFG_APP_IO1;
		xx.sys_cfg.app_select_cfg.app_io[1] = UDC_CFG_APP_IO2;
		xx.sys_cfg.app_select_cfg.app_io[2] = UDC_CFG_APP_IO3;
		xx.sys_cfg.opt_cfg_id               = UDC_CFG_APP_ID;
		xx.sys_cfg.crcLen1                  = sizeof(sys_cfg_t)-2,
		new_sn = 0;
	}else{
		udsf_memory_load2sram( SYSBOOT_AB_CFG_OUTER+curr_id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,(uint8_t*)&xx.sys_cfg,sizeof(sys_cfg_t),eQSPI_FLASH_STD);
//		for( int i=0;i<sizeof(sys_cfg_t)-2;i++ ){
//			CSTD_PRINTF("%02x ",((uint8_t*)&xx.sys_cfg.sn)[i]);
//		}
		new_sn = (xx.sys_cfg.sn+1)%(UINT_MAX/2);
		if( xx.sys_cfg.crcVal1 != udsf_get_crc((uint8_t*)&xx,sizeof(sys_cfg_t)-2) ){
			return -1;
		}
	}
	xx.sys_cfg.sn = new_sn;
	xx.sys_cfg.crcVal1 = udsf_get_crc((uint8_t*)&xx,sizeof(sys_cfg_t)-2);
	CSTD_MEMCPY((uint8_t*)&xx.paraCFG,src,len);
	xx.sys_cfg.sn = UINT_MAX;

	// sysboot只校验sys_cfg，不校验paraCFG，故最后写正确的sn
	// 写新区
	udsf_memory_erase_sector(SYSBOOT_AB_CFG_OUTER+new_id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,paramFunc->qspiMode);
	udsf_memory_program_sector(SYSBOOT_AB_CFG_OUTER+new_id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,(uint8_t*)&xx,sizeof(udc_def_t),paramFunc->qspiMode);
	udsf_memory_program_sector(SYSBOOT_AB_CFG_OUTER+new_id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,(uint8_t*)&new_sn,sizeof(new_sn),paramFunc->qspiMode);
	// 擦旧区
	udsf_memory_erase_sector(SYSBOOT_AB_CFG_OUTER+curr_id*SYSBOOT_AB_CFG_PER_SIZE,is_xip,cfg_location,paramFunc->qspiMode);
	
	return new_id;
}

#endif
